package com.kgc.est.service.impl;

import com.kgc.est.constants.Constants;
import com.kgc.est.constants.ResultEnum;
import com.kgc.est.pojo.SmsLog;
import com.kgc.est.mapper.SmsLogMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kgc.est.request.SendMsgReq;
import com.kgc.est.utils.MathUtils;
import com.kgc.est.utils.Result;
import com.kgc.est.utils.ResultUtils;
import com.kgc.est.utils.redis.RedisKeyUtils;
import com.kgc.est.utils.redis.RedisUtils;
import com.kgc.est.utils.sms.SendSmsUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


/**
 * <p>
 * 短信记录 服务实现类
 * </p>
 *
 * @author szq
 * @since 2021-10-19
 */
@RestController
@RequestMapping("/sms")
public class SmsLogServiceImpl extends ServiceImpl<SmsLogMapper, SmsLog> {

    Logger log = LoggerFactory.getLogger(SmsLogServiceImpl.class);

    @Autowired(required = false)
    private RedisUtils redisUtils;

    @Autowired(required = false)
    private SendSmsUtils sendSmsUtils;

    @Autowired(required = false)
    private SmsLogMapper smsLogMapper;

    @PostMapping("send")
    public Result sendSms(@RequestBody SendMsgReq sendMsgReq){

        log.info("sendMsgReq",sendMsgReq);

        //验证 手机号 格式是否正确
        if (!checkPhone(sendMsgReq.getPhone())){
            //说明手机号验证不通过
            return ResultUtils.returnFail("手机号输入错误", ResultEnum.FAIL.getCode());
        }

        //验证codeType 是否在规定的范围内
        if (!checkCodeType(sendMsgReq.getCodeType())){
            return ResultUtils.returnFail("验证码类型错误",ResultEnum.FAIL.getCode());
        }

        //设置短信发送状态，默认发送失败
        Integer status = Constants.Sms.STATUS_SEND_FAILED;

        //验证是否存在验证码
        if (!checkSmsCode(sendMsgReq)){
            return ResultUtils.returnFail("验证码已存在",ResultEnum.FAIL.getCode());
        }

        //先生成随机码
        String code = MathUtils.random();
        String msgResult = "Fail";
        //发送短信
        boolean sendResult = sendSmsUtils.sendSms(sendMsgReq.getPhone(), code);
        //短信发送成功后，修改status和msgResult
        if (sendResult){
            status = Constants.Sms.STATUS_SEND_SUCCESS;
            msgResult = "OK";
            log.info("手机号：{}，验证码：{}",sendMsgReq.getPhone(),code);

            //生成key
            String key = RedisKeyUtils.formatKeyWithPrefix(Constants.Redis.PREFIX_SMS,
                    sendMsgReq.getCodeType().toString(),
                    sendMsgReq.getPhone());
            //把验证码保存到redis,设置有效期为一分钟
            redisUtils.putValue(key,code,Constants.Duration.HALF_AN_HOUR);
        }



        //把短信发送信息保存到数据库中的sms_log表中
        SmsLog smsLog = new SmsLog();
        smsLog.setCodeType(sendMsgReq.getCodeType());
        smsLog.setPhone(sendMsgReq.getPhone());
        smsLog.setFailInfo(msgResult);
        smsLog.setMessage(code);
        smsLog.setStatus(status);
        log.info("要保存到sms_log表的信息{}",smsLog);
        smsLogMapper.insert(smsLog);

        return ResultUtils.returnSuccess();
    };

    /**
     * 验证手机格式是否正确
     * @param phone
     * @return
     */
    private boolean checkPhone(String phone){
        //验证手机号不为空
        if(!StringUtils.isBlank(phone)){
           return phone.matches(Constants.PHONE_REGSTR);
        }
        return false;
    }

    /**
     * 验证codeType是否在范围内
     * @param codeType
     * @return
     */
    private boolean checkCodeType(Integer codeType){

        //codeType的值不能为空
        if (null != codeType){
            //如果短信类型是这四个中的一个就可以发送
            if (codeType == Constants.Sms.TYPE_REGIST_OR_LOGIN ||
                codeType == Constants.Sms.TYPE_UP_PASS ||
                codeType == Constants.Sms.TYPE_NOTICE ||
                codeType == Constants.Sms.TYPE_SUBMIT_CHECK){
                return true;
            }
        }
        return false;
    }

    /**
     * 验证是否存在验证码
     * @param sendMsgReq
     *
     * 实现流程：
     *      根据用户传入的手机号码和验证码类型，生成一个key
     *      然后使用这个key到redis中去取值
     */
    private boolean checkSmsCode(SendMsgReq sendMsgReq){

        //通过用户的手机号和codeType生成key
        //set_sms_0_15284451626
        String key = RedisKeyUtils.formatKeyWithPrefix(Constants.Redis.PREFIX_SMS,
                sendMsgReq.getCodeType().toString(),
                sendMsgReq.getPhone());

        //根据key到redis中取出对应的value
        String code = redisUtils.getValue(key);

        if (StringUtils.isBlank(code)){
            return true; //如果验证码为空，表示之前不存在验证码，可以发送
        }

        return false;
    }
}
